package com.blockmeta.bbs.baselibrary.utils.security;


import android.util.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.*;



/**
 * @author zhouze
 * @version v1.0
 * @ClassName: RSAUtil
 * @Description: TODO
 * @date 2019-04-24
 */
public class RSAUtil {

    public static String FORWARD_PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAI2LYg2qDyQyY0lwhKY/qdoG4NebHCbH7dVduy6gXkh7SZhiKYOzYqRb9VuHAZmfkU9lhTjlmKiMFanwSGBC8YQfFUyiyaKvQu5+p3IB9SUuVTM+Fm19Z9JRQbO3jaSsaKhREZkSYE+j33pOpsHK4uGEZvFfNeN5VbYpzgxstb7TAgMBAAECgYBTukKLULBaOhAvTga5jOk9VlpET7WMXzGZyDNEdoqvF3bGVDK4fDF6hgcSWD8jD5fWPnha2r293femqcM2ZgMUwY1GZYP9Dw4+6B/lFMUctJCBRrVHjjfFwJbWPAx9Q6hONAU42aC2qOFJJXhgcgRGOeoGpTjgSnEqzmkubpAgcQJBAM7norCMrzNGT8qKXs0cuMMokfbLytM4X+uwL0JdCUpqGoqfdmlJey58iu+kKTjGypvLAdLsx1XW6rwjlufo12kCQQCvIXRH0U8zZ7XEcFnhP+5b4r5uiGWPDkcD/zyULqMU4YF1GAYuLGo/6UcPtGCfcbP1sGjfmxVDIvG0ky0L4rjbAkEAtK6lbQW+Lcm1/kqtlPMDCjJQnTPEUIXHhhuaeZqjdV+JBAtTLYik0Kij77fs4479+eTjF938CSMgY+G0c5rrGQJBAI5l/U6H+oYpxbo8QFjOytkbvQvTDAEN8uBlILS8Vw4bbk/vgNb6dkoRPB6g5A/BPDqBfkSSrO8x8qaJJQ+NAhECQC0YsqPnzkz4nsHvfLsOGWAoHgPzgGQVKCRzT1QFdojFgMr42tkE0iSYr3Q/oCWSppg0SJ+VGwUd55FEhKTbo6M=";
    public static String FORWARD_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCNi2INqg8kMmNJcISmP6naBuDXmxwmx+3VXbsuoF5Ie0mYYimDs2KkW/VbhwGZn5FPZYU45ZiojBWp8EhgQvGEHxVMosmir0LufqdyAfUlLlUzPhZtfWfSUUGzt42krGioURGZEmBPo996TqbByuLhhGbxXzXjeVW2Kc4MbLW+0wIDAQAB";

    private static final String ALGORITHM = "RSA";
    private static final String ALGORITHM_PADDING = "RSA/ECB/PKCS1Padding";
    private static final int KEYSIZE = 1024;


    /**
     * 生成RSA密钥对
     */
    public static void genKeyPair() {
        KeyPairGenerator keyPairGenerator = null;
        try {
            keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        keyPairGenerator.initialize(KEYSIZE, new SecureRandom(new SimpleDateFormat("yyyyMMdd").format(new Date()).getBytes()));
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

        System.out.println("PRIVATE_KEY:{" + Base64.encodeToString(privateKey.getEncoded(), Base64.NO_WRAP) + "}");
        System.out.println("PUBLIC_KEY:{" + Base64.encodeToString(publicKey.getEncoded(), Base64.NO_WRAP) + "}");
    }

    /**
     * 使用RSA加密字符串
     *
     * @param src
     * @return
     */
    public static String encode(String src, String publicKey) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM_PADDING);
            cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));
            return Base64.encodeToString(cipher.doFinal(src.getBytes()), Base64.NO_WRAP);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 使用RSA解密字符串
     *
     * @param src
     * @return
     */
    public static String decode(String src, String privateKey) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM_PADDING);
            cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
            return new String(cipher.doFinal(Base64.decode(src, Base64.NO_WRAP)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String decodePublic(String src, String publicKey) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM_PADDING);
            cipher.init(Cipher.DECRYPT_MODE, getPublicKey(publicKey));
            return new String(cipher.doFinal(Base64.decode(src, Base64.NO_WRAP)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取privateKey
     * @param privateKey
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKey) {
        try {
            byte[] keyBytes = Base64.decode(privateKey, Base64.NO_WRAP);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            PrivateKey privateK = keyFactory.generatePrivate(keySpec);
            return privateK;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取publicKey
     * @param publicKey
     * @return
     */
    public static PublicKey getPublicKey(String publicKey){
        try {
            byte[] bytes = Base64.decode(publicKey, Base64.NO_WRAP);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            PublicKey publicK = keyFactory.generatePublic(keySpec);
            return publicK;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获得参数格式化字符串
     * 参数名按字典排序，小写在后面
     */
    public static String getFormatParams(Map<String,Object> params){
        List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(params.entrySet());
        Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {
            @Override
            public int compare(Map.Entry<String, Object> arg0, Map.Entry<String, Object> arg1) {
                return (arg0.getKey()).compareTo(arg1.getKey());
            }
        });
        String ret = "";

        for (Map.Entry<String, Object> entry : infoIds) {
            ret += entry.getKey();
            ret += "=";
            ret += entry.getValue();
            ret += "&";
        }
        ret = ret.substring(0, ret.length() - 1);
        return ret;
    }

    public static void main(String arg[]) {
         //生成密钥
         //genKeyPair();
        Map<String, Object> map = new HashMap<>();
        map.put("test","1");
        map.put("sign","1");
        map.put("uid", "2");
        map.put("key", "test.api");
        String formatParams = getFormatParams(map);
        long time = System.currentTimeMillis() / 1000;
        String text = time + "[" + "key" + "]" + formatParams;
        String encode = encode(text, FORWARD_PUBLIC_KEY);
        String decode = decode(encode, FORWARD_PRIVATE_KEY);
        System.out.println("原始数据:{" + text + "}");
        System.out.println("加密数据:{" + encode + "}");
        System.out.println("解密数据:{" + decode + "}");
    }
}
